/**
 * Copyright (c) 2011 Technical Centre Radio Systems Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ua.tcrs.tabula.util;

import java.lang.reflect.Method;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;

public final class Predicates {
	private Predicates() {}
	
	public static <T> Predicate<T> alwaysTrue() {
		return new Predicate<T>() {
			public boolean apply( T o ) { return true; }
		};
	}
	public static <T> Predicate<T> any() {
		return alwaysTrue();
	}
	public static Predicate<Boolean> isTrue() {
		return new Predicate<Boolean>() {
			public boolean apply( Boolean o ) { return o; }
		};
	}
	public static <T> Predicate<T> equalTo( final T value ) {
		return new Predicate<T>() {
			public boolean apply( Object o ) { return o.equals( value ); }
		};
	}
	public static Predicate<Object> instanceOf( final Class<?> clazz ) {
		return new Predicate<Object>() {
			public boolean apply( Object o ) { return clazz.isInstance( o ); }
		};
	}
	public static Predicate<Class<?>> subclassOf( final Class<?> clazz ) {
		return new Predicate<Class<?>>() {
			public boolean apply( Class<?> subclass ) { return clazz.isAssignableFrom( subclass ); }
		};
	}
	public static Predicate<String> startsWith( final String prefix ) {
		return new Predicate<String>() {
			public boolean apply( String value ) { return value.startsWith( prefix ); }
		};
	}
	public static <T> Predicate<T> not( final Predicate<T> predicate ) {
		return new Predicate<T>() {
			public boolean apply( T value ) { return !predicate.apply( value ); }
		};
	}
	public static Predicate<Class<?>> classInSubpackage( final String pkgName ) {
		return new Predicate<Class<?>>() {
			public boolean apply( Class<?> c ) {
				String classPackageName = c.getPackage().getName();
				return classPackageName.equals( pkgName ) || classPackageName.startsWith( pkgName + "." );
			}
		};
	}
	public static Predicate<Class<?>> classInPackage( final String pkgName ) {
		return new Predicate<Class<?>>() {
			public boolean apply( Class<?> c ) {
				String classPackageName = c.getPackage().getName();
				return classPackageName.equals( pkgName );
			}
		};
	}
	public static Predicate<Class<?>> classInPackage( final Package pkg ) {
		return new Predicate<Class<?>>() {
			public boolean apply( Class<?> c ) {
				return c.getPackage().equals( pkg );
			}
		};
	}
	public static Predicate<AnnotatedElement> annotatedWith( final Class<? extends Annotation> annotationType ) {
		return new Predicate<AnnotatedElement>() {
			public boolean apply( AnnotatedElement annotatedElement ) {
				return annotatedElement.isAnnotationPresent( annotationType );
			}
		};
	}
}

